
#ifndef SERVICE_HPP
#define SERVICE_HPP
#include <memory>
#include <string>
#include <atomic>
#include <spdlog/spdlog.h>

class Service
{
public:
 virtual bool start() = 0 ;
 virtual bool onStart() = 0;
 virtual bool stop() = 0;
 virtual bool onStop() = 0;
 virtual bool reset() = 0;
 virtual bool onReset() = 0;
 virtual bool isRunning() = 0;
 virtual void quit() = 0;
 virtual std::string string() = 0;
 virtual void setLogger(std::shared_ptr<spdlog::logger> logger) = 0;
 virtual ~Service() = 0;
};

class BaseService
{
private:
    std::shared_ptr<Service> impl_;
    std::shared_ptr<spdlog::logger> logger_;
    std::atomic<bool> started_;
    std::atomic<bool> stopped_;
    // std::atomic<bool> quit_;
public:
    std::string name;

    BaseService(std::shared_ptr<spdlog::logger> logger,const std::string& name, std::shared_ptr<Service> impl):
    impl_(impl), logger_(logger), started_(false), stopped_(false), name(name){ }

    // SetLogger implements Service by setting a logger.
    virtual void setLogger(std::shared_ptr<spdlog::logger> logger) { logger_ = logger; }

    // Start implements Service by calling OnStart (if defined). An error will be
    // returned if the service is already running or stopped. Not to start the
    // stopped service, you need to call Reset.
    virtual void start()
    {
        bool f(false);
        if(started_.compare_exchange_strong(f,true))
        {
            if(stopped_.load()==true)
            {
                logger_->error("Not starting, {} --already stopped ", name);
                return;
            }else
            {   
                logger_->info("Starting {}", name);
            }
            if(!impl_->onStart())
            {
                started_.store(false);
            }
        }else
        {
            logger_->debug("Not starting, {} --already started", name);
            return;
        }
    }

    virtual void stop()
    {
        bool f(false);
        if(stopped_.compare_exchange_strong(f,true))
        {
            logger_->info("Stoppint {}", name);
            impl_->onStop();
        } else
        {
            logger_->debug("Stopping {} (ignoring: already stopped)", name);
        }
    }

    virtual bool isRunning()
    {
        return started_.load()==1 && stopped_.load() == 0;
    }

    virtual ~BaseService()
    {
        
    }
};

#endif // !SERVICE_HPP
